# 引入代码库
import os
import requests  # 下载所需
import sys
import json  # json数据
from tqdm import tqdm  # 进度条
import zipfile  # zip 压缩包
#import py7zr 
import subprocess
import winreg
import ctypes 
from pathlib import Path #获取路径


# 全局变量
clear = "cls"  # 清屏

# 定义颜色
red = "\033[31m"  # 红色
reset = "\033[0m"  # 用于重置颜色
warn = "\033[93m"  #中等提醒颜色

# mypath = os.path.dirname(os.path.abspath(sys.executable))#os.path.dirname(os.path.abspath(__file__)) #获取自己本地路径
mypath = ".\\"
# print(mypath)
# ###################################### 预加载程序 #############################################
# +--------------------------------------------------------------------------------------------+
# 配置文件-设置
config_path_ini = os.path.join(mypath,"conf", "ini.json")
with open(config_path_ini, "r", encoding='utf-8') as file:
    conf_json = json.load(file)
# ++------------------------------------------------------------------------------------------++

# +--------------------------------------------------------------------------------------------+
# 加载下载源
def source_loading():
    config_path_source = os.path.join(mypath,"source", "default.json")
    with open(config_path_source, "r", encoding='utf-8') as file1:
        source_dl = json.load(file1)
        return source_dl
# ++------------------------------------------------------------------------------------------++

# +--------------------------------------------------------------------------------------------+
# 判断更新源-conf
if conf_json["seting"]["update_y"] == True:
    # dl_file()
    print()
# ++------------------------------------------------------------------------------------------++

# +--------------------------------------------------------------------------------------------+
# 判断更新软件
"""
预留区
"""
# ++------------------------------------------------------------------------------------------++

# ###################################### 函数调用区 #############################################
# +--------------------------------------------------------------------------------------------+
# 下载文件
def download_file(url, save_dir):
    try:
        # 从URL中提取文件名
        filename = os.path.basename(url)

        # 确保保存目录存在，如果不存在则创建
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)

        # 完整的文件保存路径
        save_path = os.path.join(save_dir, filename)

        # 发起GET请求，以流式方式获取数据
        response = requests.get(url, stream=True)

        # 确保请求成功
        if response.status_code == 200:
            # 获取文件总大小，用于设置进度条
            total_size = int(response.headers.get('content-length', 0))
            # 使用tqdm创建进度条
            with tqdm(total=total_size, unit='B', unit_scale=True, desc=filename) as bar:
                # 以二进制写入模式打开文件
                with open(save_path, 'wb') as file:
                    # 按块读取数据
                    for data in response.iter_content(chunk_size=1024):
                        # 写入数据
                        file.write(data)
                        # 更新进度条
                        bar.update(len(data))
            print(f"文件已下载到 {save_path}")
            return [True, f'{save_path}']
        else:
            print(f"请求失败，状态码：{response.status_code}")
            return [False]
    except requests.exceptions.RequestException as e:
        print(f"网络请求异常：{e}")
        return [False]
    except OSError as e:
        print(f"文件操作异常：{e}")
        return [False]
    except Exception as e:
        print(f"未知错误：{e}")
        return [False]
# ++------------------------------------------------------------------------------------------++

# +--------------------------------------------------------------------------------------------+
# 解压文件
# def unzip_with_progress(zip_path, extract_to):
#     # 打开ZIP文件
#     with zipfile.ZipFile(zip_path) as zip_ref:
#         # 获取文件列表
#         total_files = zip_ref.infolist()
#         # 解压文件并显示进度条
#         for member in tqdm(total_files, desc='Extracting', unit='file'):
#             # 解压每个文件
#             zip_ref.extract(member, extract_to)
def unzip_with_progress(archive_path, extract_to):
    # 检查文件扩展名
    if archive_path.endswith('.zip'):
        # 解压 ZIP 文件
        with zipfile.ZipFile(archive_path) as zip_ref:
            total_files = zip_ref.infolist()
            for member in tqdm(total_files, desc='Extracting', unit='file'):
                zip_ref.extract(member, extract_to)
    elif archive_path.endswith('.7z'):
        # 解压 7z 文件
        if os.name == 'nt':  # Windows
            # 检查7zr.exe是否存在
            if not os.path.exists('7zr.exe'):
                print("Error: 7zr.exe not found in the current directory.")
                return
            # 构造命令
            command = f'7zr.exe x "{archive_path}" -o"{extract_to}" -aoa'
        else:  # Linux 或其他系统
            print("Please install 7zip environment.")
            return

        # 执行命令
        try:
            subprocess.run(command, shell=True, check=True)
            print("Extraction completed.")
        except subprocess.CalledProcessError as e:
            print(f"Error during extraction: {e}")
    else:
        print("Unsupported archive format.")
# 示例调用
# unzip_with_progress("example.7z", "output_directory")


# ++------------------------------------------------------------------------------------------++

# +--------------------------------------------------------------------------------------------+
# 添加环境变量
def append_registry_path(new_path):
    try:
        # 以管理员权限操作注册表
        key = winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
            0, 
            winreg.KEY_ALL_ACCESS | winreg.KEY_QUERY_VALUE
        )
        
        # 获取当前Path值（自动处理REG_EXPAND_SZ类型）
        current_path, reg_type = winreg.QueryValueEx(key, "Path")
        
        # 避免重复追加路径（可选）
        if new_path in current_path.split(';'):
            print("路径已存在，无需重复添加")
            return
        
        # 追加新路径并更新（保留原数据类型）
        updated_path = f"{current_path};{new_path}" if current_path else new_path
        winreg.SetValueEx(key, "Path", 0, reg_type, updated_path)
        winreg.CloseKey(key)

        # 广播环境变量更新消息（无需重启）
        HWND_BROADCAST = 0xFFFF
        WM_SETTINGCHANGE = 0x1A
        ctypes.windll.user32.SendMessageW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, "Environment")
        
        print(f"成功追加路径：{new_path}")
    except PermissionError:
        print("错误：请以管理员身份运行程序")
    except Exception as e:
        print(f"操作失败：{str(e)}")
# 删除环境变量
def delete_specific_path(target_path):
    try:
        # 打开系统级环境变量注册表键
        key = winreg.OpenKey(
            winreg.HKEY_LOCAL_MACHINE,
            r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
            0,
            winreg.KEY_ALL_ACCESS
        )
        
        # 获取当前Path值和数据类型
        current_path, reg_type = winreg.QueryValueEx(key, "Path")
        
        # 精确匹配并过滤目标路径
        filtered_paths = [
            p.strip() 
            for p in current_path.split(';') 
            if p.strip().lower() != target_path.lower()  # 忽略大小写
        ]
        new_path = ';'.join(filtered_paths)
        
        # 更新注册表并广播变更
        winreg.SetValueEx(key, "Path", 0, reg_type, new_path)
        winreg.CloseKey(key)
        ctypes.windll.user32.SendMessageW(0xFFFF, 0x1A, 0, "Environment")
        
        print(f"路径 {target_path} 已删除")
    except PermissionError:
        print("错误：需管理员权限运行")
    except Exception as e:
        print(f"操作失败：{str(e)}")
# ++------------------------------------------------------------------------------------------++

# +--------------------------------------------------------------------------------------------+
# 查找文件夹
def find_file(directory, filename):
    """
    Search for a file by name in the given directory and its subdirectories.
    If found, print the absolute path of the file.
    
    :param directory: The root directory to start the search from.
    :param filename: The name of the file to search for.
    """
    for root, dirs, files in os.walk(directory):
        if filename in files:
            return os.path.join(root, filename)
    return None
# ++------------------------------------------------------------------------------------------++

# +--------------------------------------------------------------------------------------------+
# 命令处理
class input_c():
    def mode(a):
        if a == "1":
            w = True  # 定义循环
            source_dl = source_loading()  # 加载下载源
            while w:
                # 输入命令
                input_text = input("XM_CPath#> ")

                args = input_text.split()  # 将输入的字符串分割成列表，模拟命令行参数
                
                # 判断空白或没有数据
                if input_text == "" or len(args) == 0:
                    print(end='')
                else:
                    # 定义第一个输入的指令
                    if_text = args[0]
                    if if_text == "clear":  # 清屏
                        os.system(clear)
                    elif if_text == "exit":  # 退出
                        w = False 
                    elif if_text == "install":  # 安装软件或编程语言
                        if len(args) > 1:  # 判断args（参数）后有没有数据
                            if_name = False
                            for x_install in source_dl['Lang']:
                                name_json = x_install['name']
                                PathName = x_install['pn']
                                if name_json.lower() == args[1]:
                                    url_json = x_install['url']
                                    size_json = x_install['size']
                                    time_json = x_install['time']
                                    type_json = x_install['type']
                                    version_json = x_install['version']
                                    print(f"------------{name_json}------------")
                                    print(
                                        f"版本：{version_json}\n更新时间：{time_json}\n大小：{size_json}\n安装方式：{type_json}\n下载链接：{url_json}\n+-----------------------------+")
                                    print()
                                    if type_json == "make&zip":
                                        print()
                                    else:
                                        dlname = input(f"是否下载并安装 {name_json} [Y/n]:")
                                        if dlname.lower() == 'y':  # 判断是否安装
                                            if_dl = download_file(url_json, "download/")  # 下载文件 到目录
                                            if if_dl[0] == True:  # 判断数组中的返回值是否有路径压缩包
                                                print("开始解压文件...")
                                                Path_separator = os.path.join(os.getcwd(), 'Lang',
                                                                              name_json)  # 使用系统的目录分隔符
                                                unzip_with_progress(if_dl[1], f"./Lang/{name_json}/")  # 解压压缩包

                                                file_path = find_file(Path_separator, PathName)  # 查找文件夹是否有执行文件
                                                if file_path:  # 判断返回值文件是否存在
                                                    print(f"File found at: {file_path}")
                                                    #add_to_path(file_path.replace(PathName,''))
                                                    append_registry_path(file_path.replace(PathName,'')) #写系统环境
                                                    print(file_path.replace(PathName,''))
                                                else:
                                                    print(f"没有找到文件，失败")
                                    no_name = False #语言存在
                                    break   
                                else:  #循环-判断语言不存在变量
                                    no_name = True #语言不存在
                            if no_name == True: #判断不存在
                                print(f"{red}“{args[1]}” not in source\n{reset}")
                        else:
                            print(f"{warn}install <lang>\n{reset}")
                            
                    elif if_text == "show": #判断输入为 show -- 查看函数
                        if len(args) > 1:
                            if args[1] == "source":

                                grep = "*"
                                if len(args) > 2:
                                    grep = args[2]

                                for json_source in source_dl["Lang"]:
                                    name_json = json_source['name']
                                    url_json = json_source['url']
                                    version_json = json_source['version']
                                    time_json = json_source['time']
                                    size_json = json_source['size']
                                    type_json = json_source['type']

                                    if grep == "*":  # source后面没有参数--输出全部
                                        print(f"------------{name_json}------------")
                                        print(
                                            f"版本：{version_json}\n更新时间：{time_json}\n大小：{size_json}\n安装方式：{type_json}\n下载链接：{url_json}\n+-----------------------------+")
                                        print()
                                        no_name = False #判断是否存在-存在
                                    else:
                                        if grep.lower() == name_json.lower():                                            
                                            print(f"------------{name_json}------------")
                                            print(
                                                f"版本：{version_json}\n更新时间：{time_json}\n大小：{size_json}\n安装方式：{type_json}\n下载链接：{url_json}\n+-----------------------------+")
                                            print()
                                            no_name = False #判断是否存在-存在
                                            break
                                        else:
                                            no_name = True #判断是否存在-不存在
                                if no_name == True:
                                    print(f"{red} “{args[2]}” not in source{reset}\n")

                            elif  args[1] == "预留": 
                                print("")
                            
                            else: # 判断查看找不到资源
                                print(f"{red} “{args[1]}” not is code{reset} ")

                        else: #只输入show 提示
                            print(f"{warn}show <type> <1>{reset}\n")     


                    elif if_text == "sf":  # 判断输入为 sf -- 安装软件
                        if len(args) > 1:
                            if args[1] == "install":
                                if len(args) > 2:  # 确保 args[2] 存在
                                    software_name = args[2].lower()
                                    no_name = True  # 默认软件不存在
                                    for json_source in source_dl["softwaer"]:  # 修正拼写错误
                                        name_json = json_source['name']
                                        url_json = json_source['url']
                                        if name_json.lower() == software_name:  # 判断源中是否存在
                                            version_json = json_source['version']
                                            time_json = json_source['time']
                                            size_json = json_source['size']
                                            type_json = json_source['type']
                                            print(f"------------{name_json}------------")
                                            print(f"版本：{version_json}\n更新时间：{time_json}\n大小：{size_json}\n安装方式：{type_json}\n下载链接：{url_json}\n+-----------------------------+")
                                            print()
                                            # 提示用户是否下载并安装
                                            dlname = input(f"是否下载并安装 {name_json} [Y/n]:")
                                            if dlname.lower() == 'y':  # 判断是否安装
                                                if_dl = download_file(url_json, "download/")  # 下载文件到目录
                                                if if_dl[0] == True:  # 判断数组中的返回值是否有路径压缩包
                                                    print("开始解压文件...")
                                                    Path_separator = os.path.join(os.getcwd(), 'software', name_json)  # 使用系统的目录分隔符
                                                    unzip_with_progress(if_dl[1], f"./software/{name_json}/")  # 解压压缩包
                                            no_name = False  # 判断是否存在-存在
                                            break
                                    if no_name:  # 如果软件不存在
                                        print(f"{red} “{software_name}” not in source{reset}\n")
                                else:
                                    print(f"{warn}sf install <software_name>{reset}\n")
                            else:
                                print(f"{red} “{args[1]}” not is code{reset} ")
                        else:
                            print(f"{warn}sf <command> <software_name>{reset}\n")
                         




                    elif input_text == "server":  # 服务器---服务 #需要安装appsls
                        if len(args) > 1:
                            if args[1] == "web":
                                if "-p" in args and len(args) > args.index('-p') + 1:  # 判断是否是该函数 和 判断为空报错
                                    webport = args[args.index('-p') + 1]  # 获取参数后面的数据--网页端口

                                if "-r" in args and len(args) > args.index('-r') + 1:  # 判断是否是该函数 和 判断为空报错
                                    webdir = args[args.index('-r') + 1]  # 获取参数后面的数据--网页目录

                            elif args[1] == "ftp":
                                if "-p" in args and len(args) > args.index('-p') + 1:  # 判断是否是该函数 和 判断为空报错
                                    webport = args[args.index('-p') + 1]  # 获取参数后面的数据--网页端口

                                if "-r" in args and len(args) > args.index('-r') + 1:  # 判断是否是该函数 和 判断为空报错
                                    webdir = args[args.index('-r') + 1]  # 获取参数后面的数据--网页目录

                    else:  # 其他事件--输入命令
                        print(f"{red}error: “{input_text}” Not is code{reset}")
                        print()
        else:  # 模式1
            print()
# ++------------------------------------------------------------------------------------------++

# main 主程序
input_c.mode("1")
